const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
const WorkBoxPlugin = require('workbox-webpack-plugin')
const webpack = require('webpack')
const { ModuleFederationPlugin } = require('webpack').container
// const json5 = require('json5')
// const yaml = require('yaml')
// const toml = require('toml')

const isDev = process.env.NODE_ENV === 'development'
console.log(isDev);

module.exports = {
  entry: {
    // main: {
    //   import: './src/main.js',
    //   // 都依赖模块shared
    //   dependOn: 'lodash',
    //   // runtime: 'runtime-main'
    // },
    // other: {
    //   import: './src/other.js',
    //   dependOn: 'lodash',
    //   // runtime: 'runtime-main'
    // },
    // 公共lodash抽离出来
    // lodash: 'lodash',
    main: './src/main.js',
    other: './src/other.js'
  },
  experiments: {
    // 当library中type:module时, 需开启
    outputModule: false
  },
  output: {
    // 打包后的文件夹名
    path: path.resolve(__dirname, '../dist'),
    // 打包的asset文件名
    assetModuleFilename: 'images/[contenthash][ext]',
    pathinfo: false,
    // 清除旧的打包资源
    clean: true,
    library: {
      // 打包出的js导出的全局名称
      name: '[name]js',
      // umd:打包成amd commonjs script标签直接引入 三个都可以支持的包; module: 只支持esmodule
      type: 'umd'
    },
    // 修改全局对象
    globalObject: 'globalThis'
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        // loader从右向左执行
        use: [isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
        {
          loader: 'css-loader',
          options: {
            modules: true
          }
        },
          'postcss-loader'
        ]
      },
      {
        test: /\.scss$/,
        // 从右向左执行
        use: [
          isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              // 将css当模块化使用，避免样式污染
              modules: true
            }
          },
          'sass-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.js$/,
        // 显式排除不处理的包
        exclude: '/node_modules/',
        // 显式指定要处理的js, 提升打包速率
        include: path.resolve(__dirname, '../src'),
        use: [
          {
            // babel-loader: 将es6转换成es5的桥梁 @babel-core: babel核心 @babel/preset-env: babel预设，babel插件的集合
            loader: 'babel-loader',
            options: {
              // 预设好所需要的插件
              presets: [
                '@babel/preset-env'
              ],
              // plugins: [
              //   [
              //     '@babel/plugin-transform-runtime'
              //   ]
              // ]
            }
          },
          // 多线程打包(合理使用)
          {
            loader: 'thread-loader',
            options:{
              workers: 2
            }
          }
        ]
      },
      {
        test: /\.ts$/i,
        exclude: /node_modules/,
        use: [{
          // loader: 'ts-loader',
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-typescript']
          }
        }]
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        // asset/inline: 将图片转成base64  asset/resource(加载任何资源): 将图片转换成url地址
        // asset/source: 导出资源源代码(用于文件,文本)  asset: 两者都要
        type: 'asset',
        // 针对具体文件打包出的名字(优先级高于output的assetModuleFilename)
        generator: {
          filename: 'images/[contenthash][ext]'
        },
        // asset 特有的(不同情况采取不同策略)
        parser: {
          // 小于1024的图片转成base64
          dataUrlCondition: {
            maxSize: 1024 * 1
          }
        }
        // use: [
        //   {
        //     loader: 'file-loader',
        //     options: {
        //       name: '[name].[ext]',
        //       outputPath: 'images/'
        //     }
        //   },
        //   {
        //     loader: 'url-loader',
        //     options: {

        //     }
        //   }
        // ]
      },
      {
        test: /\.(svg)$/i,
        type: 'asset/inline',
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource'
      },
      // {
      //   test: '/\.(tsv|csv)$/',
      //   // 转换成数组 
      //   type: 'csv-loader'
      // },
      // {
      //   test: '/\.xml$/',
      //   // 将xml转换成对象
      //   type: 'xml-loader'
      // },
      // {
      //   test: '/\.toml$/',
      //   type: 'json',
      //   parser: {
      //     // 自定义解析toml文件
      //     parse: toml.parse
      //   }
      // },
      // {
      //   test: '/\.yaml$/',
      //   type: 'json',
      //   parser: {
      //     // 自定义解析yaml文件
      //     parse: yaml.parse
      //   }
      // },
      // {
      //   test: '/\.json5$/',
      //   type: 'json',
      //   parser: {
      //     // 自定义解析json5文件
      //     parse: json5.parse
      //   }
      // },
      // {
      //   test: require.resolve('../src/main.js'),
      //   use: {
      //     loader: 'imports-loader',
      //     options: {
      //       // 将this指向window
      //       wrapper: 'window'
      //     }
      //   }
      // },
      // {
      //   test: require.resolve('../src/globals.js'),
      //   use: {
      //     loader: 'exports-loader',
      //     options: {
      //       // 将globals.js当commonjs使用, 并导出g,fn属性 module.exports = { g, fn }
      //       type: 'commonjs',
      //       exports: 'g,fn'
      //     }
      //   }
      // }
    ]
  },
  // 快速查找资源/路径
  resolve: {
    alias: {
      '@': path.resolve(__dirname, '../src'),
    },
    // 识别顺序, 前面的先识别
    extensions: ['.ts', '.js']
  },
  plugins: [
    // 多页面可申请多个HtmlWebpackPlugin
    new HtmlWebpackPlugin({
      template: './public/index.html',
      title: 'webpack demo',
      // 打包出的html文件名(默认index)
      // filename: 'main.html',
      // 自定义需要将哪些打包的js文件引入该html下
      // chunks: ['main'],
      // 定义什么位置引入打包后的js
      inject: 'body',
      // 根据环境变量配置引入打包后js的路径
      publicPath: isDev ? '/' : '/dist/'
    }),
    // new HtmlWebpackPlugin({
    //   template: './public/index.html',
    //   filename: 'other.html',
    //   chunks: ['other']
    // }),

    // 将css文件提取到单独的文件中
    // css / js 并行加载  
    new MiniCssExtractPlugin({
      filename: 'styles/[contenthash].css '
    }),
    // 查看打包分析
    // new BundleAnalyzerPlugin(),

    // workbox开启离线缓存(服务关闭的情况下也可以访问，需与浏览器配合)
    // new WorkBoxPlugin.GenerateSW({
    //   clientsClaim: true,
    //   skipWaiting: true
    // }),

    // 将第三方包提供全局变量(先安装包，再定义全局变量)
    // new webpack.ProvidePlugin({
    //   _: 'lodash',
    //   $: 'jquery'
    // })

    // 模块联邦(将多项目之间的组件/库进行共享使用)配置
    // 模块联邦使用
    // import('main/Async').then(res => {})
    // new ModuleFederationPlugin({
    //   name: 'main',
    //   filename: 'remoteEntry.js',
    //   // 要使用的其他项目暴露的js
    //   remotes: {
    //     // key与暴露者定义的name相同 main@http://xxx/remoteEntry.js
    //     'main': 'main@具体的地址'
    //   },
    //   // 暴露的组件或js
    //   exposes: {
    //     './Async': '../src/async.js'
    //   },
    //   // 使用的第三方组件/库
    //   shared: {}
    // })
  ],
  // externalsType: 'script',
  // 将第三方插件不打包, 默认用户已经安装该插件
  externals: {
    // jquery: [
    //   `/utils/jquery.js`,
    //   '$'
    // ],
    // or
    // jquery: {
    //   commonjs: 'jQuery',
    //   commonjs2: 'jQuery',
    //   global: 'jQuery',
    //   root: '$'
    // }
  },
  optimization: {
    // 开启treeshaking(默认开启)
    usedExports: true,
    splitChunks: {
      // 自动将静态公共代码进行抽离
      // chunks: ['all']

      // 将第三方文件都抽离到一个文件中，进行缓存
      cacheGroups: {
        vendor: {
          test: '/[\\/]node_modules[\\/]/',
          name: 'vendors',
          chunks: 'all'
        }
      }
    }
  }
}